package cmd_handler

import (
	"time"

	"xgame.go_server/comm/async_op"
	"xgame.go_server/comm/lazy_save"
	"xgame.go_server/comm/log"
	"xgame.go_server/dao"
	"xgame.go_server/lso"
	"xgame.go_server/model"
	"xgame.go_server/msg"
)

// OnUserOffLine 当用户离线
func OnUserOffLine(ctx MyCmdCtx) {
	if nil == ctx {
		return
	}

	log.Info("用户离线, userId = %d", ctx.GetUserId())

	// 事先获取用户
	user := model.GetUserGroup().GetByUserId(ctx.GetUserId())

	getBroadcaster().removeCmdCtxBySessionUId(ctx.GetSessionUId())
	model.GetUserGroup().RemoveByUserId(ctx.GetUserId())

	getBroadcaster().broadcast(
		&msg.UserQuitResult{
			QuitUserId: uint32(ctx.GetUserId()),
		},
	)

	if nil == user {
		log.Warning(
			"未找到用户, userId = %d",
			ctx.GetUserId(),
		)

		return
	}

	// 放弃延迟保存
	userLso := lso.GetUserLso(user)
	lazy_save.Discard(userLso)

	isDone := make(chan bool)

	// 通过异步操作保存数据
	async_op.Process(
		async_op.BindId(ctx.GetUserId()),
		func() {
			log.Info(
				"用户离线保存, userId = %+v",
				user.UserId,
			)

			dao.GetUserDao().SaveOrUpdate(user)
			isDone <- true
		},
		nil,
	)

	select {
	case <-isDone:
		break

	case <-time.After(time.Duration(5) * time.Second):
		// 超时等待 5 秒
		break
	}

	log.Info(
		"用户离线处理完成, userId = %+v",
		user.UserId,
	)
}
